package logic

import (
	"context"
	"strconv"
	"time"

	"probe-users/internal/errorx"
	"probe-users/internal/model"
	"probe-users/internal/svc"
	"probe-users/internal/utils"
	"probe-users/pb/users"

	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/logx"
)

type CreateUserLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewCreateUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateUserLogic {
	return &CreateUserLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *CreateUserLogic) CreateUser(in *users.CreateUserRequest) (*users.CreateUserResponse, error) {
	// 权限校验：只有管理员有权限创建用户
	if err := l.checkPermission(in.AdminToken); err != nil {
		return nil, err
	}

	// 参数验证（用户名、密码、角色ID等）
	if err := l.validateCreateParams(in); err != nil {
		return nil, err
	}

	// 检查用户名是否已存在
	_, err := l.svcCtx.UserModel.FindByUsername(in.Username)
	if err == nil {
		return nil, errorx.ErrUsernameExists
	}
	if !errors.Is(err, errorx.ErrUserNotFound) {
		return nil, errors.Wrapf(err, "查询用户名失败: %s", in.Username)
	}

	// 检查邮箱是否已存在（非空时检查）
	if in.Email != "" {
		_, err := l.svcCtx.UserModel.FindByEmail(in.Email)
		if err == nil {
			return nil, errorx.ErrEmailExists
		}
		if !errors.Is(err, errorx.ErrUserNotFound) {
			return nil, errors.Wrapf(err, "查询邮箱失败: %s", in.Email)
		}
	}

	// 检查手机号是否已存在（非空时检查）
	if in.Phone != "" {
		_, err := l.svcCtx.UserModel.FindByPhone(in.Phone)
		if err == nil {
			return nil, errorx.ErrPhoneExists
		}
		if !errors.Is(err, errorx.ErrUserNotFound) {
			return nil, errors.Wrapf(err, "查询手机号失败: %s", in.Phone)
		}
	}

	// 密码加密（复用注册逻辑的加密方法）
	hashedPassword, err := utils.HashPassword(in.Password)
	if err != nil {
		return nil, errors.Wrapf(err, "密码加密失败")
	}

	// 验证角色ID是否存在（管理员创建时需指定角色）
	targetRole, err := l.svcCtx.RoleModel.FindOne(in.RoleId)
	if err != nil {
		return nil, errors.Wrapf(err, "角色ID不存在: %d", in.RoleId)
	}

	// 创建用户记录
	now := time.Now()
	user := &model.User{
		Username:  in.Username,
		Password:  hashedPassword,
		Email:     in.Email,
		Phone:     in.Phone,
		Nickname:  in.Nickname,
		RoleID:    targetRole.ID, // 使用指定的角色ID
		CreatedAt: now,
		UpdatedAt: now,
	}

	// 插入数据库
	result, err := l.svcCtx.UserModel.Insert(user)
	if err != nil {
		return nil, errors.Wrapf(err, "创建用户失败")
	}

	// 获取新用户ID
	userID, err := result.LastInsertId()
	if err != nil {
		return nil, errors.Wrapf(err, "获取用户ID失败")
	}
	user.ID = userID

	// 绑定用户与角色（Casbin g规则：用户继承角色权限）
	if err := l.bindUserRole(userID, targetRole.ID); err != nil {
		return nil, errors.Wrapf(err, "用户角色绑定失败")
	}

	return &users.CreateUserResponse{
		Id:       user.ID,
		Username: user.Username,
		RoleId:   user.RoleID,
		Message:  "用户创建成功",
	}, nil
}

// 权限校验：检查管理员是否有创建用户的权限
func (l *CreateUserLogic) checkPermission(adminToken string) error {
	// 解析管理员Token获取角色信息
	claims, err := utils.ParseToken(adminToken, l.svcCtx.Config.JWTAuth.AccessSecret)
	if err != nil {
		return errorx.ErrInvalidToken
	}

	// Casbin权限检查（sub=角色ID字符串，obj=user，act=create）
	hasPerm, err := l.svcCtx.Enforcer.Enforce(strconv.FormatInt(claims.RoleId, 10), "user", "create:other")
	if err != nil {
		return errors.Wrapf(err, "权限检查失败")
	}
	if !hasPerm {
		return errorx.ErrCreateUserPermissionDenied
	}
	return nil
}

// 参数验证：比注册逻辑多验证角色ID
func (l *CreateUserLogic) validateCreateParams(in *users.CreateUserRequest) error {
	// 复用注册逻辑的用户名/密码校验
	if err := l.validateBaseParams(in); err != nil {
		return err
	}

	// 额外验证角色ID（管理员创建必须指定角色）
	if in.RoleId <= 0 {
		return errorx.ErrRoleIdInvalid
	}
	if _, err := l.svcCtx.RoleModel.FindOne(in.RoleId); err != nil {
		return errors.Wrapf(err, "角色ID不存在: %d", in.RoleId)
	}

	return nil
}

// 基础参数验证（复用注册的用户名/密码规则）
func (l *CreateUserLogic) validateBaseParams(in *users.CreateUserRequest) error {
	if in.Username == "" {
		return errorx.ErrUsernameNotEmpty
	}
	if len(in.Username) < 3 || len(in.Username) > 20 {
		return errorx.ErrUsernameLengthInvalid
	}
	if in.Password == "" {
		return errorx.ErrPasswordNotEmpty
	}
	if len(in.Password) < 6 || len(in.Password) > 32 {
		return errorx.ErrPasswordLengthInvalid
	}
	return nil
}

// 绑定用户与角色到Casbin（用户继承角色权限）
func (l *CreateUserLogic) bindUserRole(userId, roleId int64) error {
	_, err := l.svcCtx.Enforcer.AddGroupingPolicy(
		strconv.FormatInt(userId, 10), // 用户ID字符串
		strconv.FormatInt(roleId, 10), // 角色ID字符串
	)
	return err
}
